import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
//提供 JavaScript 引擎，用于计算表达式（如1+2）
import javax.swing.*;
//提供图形界面组件（如窗口、按钮、文本框）。
import java.awt.*;
//提供基本的 GUI 工具（布局管理器、颜色、字体）。
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
//处理用户交互事件（如点击、鼠标移动）。
import java.io.File;
//用于文件操作（音效加载）
import java.text.SimpleDateFormat;
import java.util.Date;
//处理日期时间格式。
import javax.sound.sampled.*;
//播放音效

public class Calculator extends JFrame implements ActionListener {
    //extends JFrame：继承JFrame类，使Calculator成为窗口应用。
    //implements ActionListener：实现按钮点击事件的监听接口。
    private JPanel north, center;
    //north 和 center：界面的顶部和中间面板。
    private JTextField field;
    //field：显示计算结果的文本框。
    private JButton[] btns;
    //btns：存储所有按钮的数组。
    private Clip clickSound;
    //clickSound：按钮点击音效的剪辑对象。

    public Calculator() {
        setTitle("计算器");
        //设置窗口标题
        setSize(700, 700);
        // 设置窗口大小（宽×高）
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        // 关闭窗口时退出程序
        setLocationRelativeTo(null);
         // 窗口居中显示
        loadSound();
         // 加载按钮点击音效
        initComponent();
        // 初始化界面组件
        setVisible(true);
        // 显示窗口
    }

    private void loadSound() {
        try {
            File soundFile = new File("D:\\2\\Test3\\clear.wav");
            if (soundFile.exists()) {
                AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(soundFile);
                clickSound = AudioSystem.getClip();
                clickSound.open(audioInputStream);
            }

        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("音效加载失败");
        }
    }

    private void playClickSound() {
        if (clickSound != null) {
            clickSound.setFramePosition(0);
            // 重置音效到开头
            clickSound.start();
             // 播放音效
        }
    }

    private void initComponent() {
      // 创建面板并设置背景色
        north = new JPanel();
        north.setBackground(new Color(240, 240, 240)); // 浅灰色
        center = new JPanel();
        center.setBackground(new Color(220, 220, 220));// 灰色
        // 初始化文本框
        field = new JTextField();
        field.setPreferredSize(new Dimension(700, 150));
        // 设置大小
        field.setEditable(false);
        // 禁止用户直接输入，只能通过按钮操作
        field.setFont(new Font("SansSerif", Font.BOLD, 35));
        // 设置字体
        field.setHorizontalAlignment(JTextField.RIGHT);
        // 文本右对齐
        field.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
        // 设置内边距
        field.setBackground(new Color(255, 255, 255));
        // 白色背景

        String[] str = new String[]{
            "7", "8", "9", "+",
            "4", "5", "6", "-",
            "1", "2", "3", "×",
            "0", ".", "=", "÷",
            "C", "B", "T", "S"
        };

        btns = new JButton[str.length];
        Color[] originalColors = new Color[str.length];
        // 存储按钮原始颜色
        
        for (int i = 0; i < btns.length; i++) {
            btns[i] = new JButton(str[i]);
            btns[i].setFont(new Font("SansSerif", Font.BOLD, 25));
            // 设置按钮字体
            btns[i].setFocusPainted(false);
             // 取消按钮周围的焦点框
            
            // 设置基础颜色
            if (i == 16) btns[i].setBackground(new Color(255, 100, 100)); // C红色
            else if (i == 17) btns[i].setBackground(new Color(255, 200, 100)); // B橙色
            else if (i == 18) btns[i].setBackground(new Color(100, 200, 100)); // T绿色
            else if (i == 19) btns[i].setBackground(new Color(100, 100, 255)); // S蓝色
            else if (i == 14) btns[i].setBackground(new Color(150, 200, 255)); // =浅蓝色
            else btns[i].setBackground(new Color(240, 240, 240));//其他按钮灰色
            
            originalColors[i] = btns[i].getBackground();
            //保持原始颜色
            
            // 添加按钮效果
            final JButton currentBtn = btns[i];
            final Color baseColor = originalColors[i];
            
            currentBtn.addMouseListener(new MouseAdapter() {
                @Override
                public void mouseEntered(MouseEvent e) {
                    currentBtn.setBackground(darkenColor(baseColor, 30));
                    // 鼠标悬停时颜色加深30
                }

                @Override
                public void mouseExited(MouseEvent e) {
                    currentBtn.setBackground(baseColor);
                    // 鼠标离开时恢复原色
                }
                
                @Override
                public void mousePressed(MouseEvent e) {
                    currentBtn.setBackground(darkenColor(baseColor, 50));
                    // 鼠标按下时颜色加深50
                    playClickSound();
                    // 播放点击音效
                }
                
                @Override
                public void mouseReleased(MouseEvent e) {
                    currentBtn.setBackground(darkenColor(baseColor, 30));
                    // 鼠标释放时保持悬停颜色
                }
            });
        }
         // 设置面板布局 
        north.setLayout(new BorderLayout());
        // 顶部面板使用边界布局
        center.setLayout(new GridLayout(5, 4, 5, 5));
        //中间面板使用5×4网格布局，间距5px 
        center.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
        // 设置面板边距 // 添加组件到面板 
        north.add(field, BorderLayout.CENTER);
        // 文本框添加到顶部面板中间 
        for (JButton btn : btns) {
            center.add(btn);
        }
        
        add(north, BorderLayout.NORTH);
        // 文本框添加到顶部面板中间 
        add(center, BorderLayout.CENTER);
        // 中间面板放在窗口中央 // 为所有按钮添加点击事件监听 for 

        for (JButton btn : btns) {
            btn.addActionListener(this);
            // 点击事件由当前类处理
        }
    }

    // 辅助方法：生成更暗的颜色
    private Color darkenColor(Color color, int amount) {
        int r = Math.max(color.getRed() - amount, 0);
         // 确保红色值不小于0
        int g = Math.max(color.getGreen() - amount, 0);
        int b = Math.max(color.getBlue() - amount, 0);
        return new Color(r, g, b);
    }
    // 判断字符是否为运算符
    private boolean isOperator(char c) {
        return c == '+' || c == '-' || c == '×' || c == '÷';
        // 判断字符是否为数字或小数点 
    }

    private boolean isNumberOrDot(char c) {
        return Character.isDigit(c) || c == '.';
    }

    private void setBtnText(String text) {
        String currentText = field.getText();
        
        switch (text) {
            case "C":
                 // 清空按钮
                field.setText("");
                // 清空文本框
                break;
            case "B":
                 // 退格按钮
                if (!currentText.isEmpty()) {
                    // 删除最后一个字符 
                    field.setText(currentText.substring(0, currentText.length() - 1));
                }
                break;
            case "T":
                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                field.setText(dateFormat.format(new Date()));
                break;
            case "S":
                try {
                    double number = Double.parseDouble(currentText);
                    if (number < 0) {
                        field.setText("无效输入");
                    } else {
                        double result = Math.sqrt(number);
                        field.setText(String.valueOf(result));
                    }
                } catch (NumberFormatException e) {
                    field.setText("格式错误");
                }
                break;
            case "=":
                calculate();
                break;
            case ".":
                if (currentText.isEmpty()) {
                    field.setText("0.");
                    // 空文本框时自动补0
                } else {
                    char lastChar = currentText.charAt(currentText.length() - 1);
                    if (isNumberOrDot(lastChar)) {
                        // 最后一个字符是数字或小数点，检查是否已有小数点 
                        String[] parts = currentText.split("[+\\-×÷]");
                        String lastNumber = parts[parts.length - 1];
                        if (!lastNumber.contains(".")) {
                            field.setText(currentText + text);
                            // 追加小数点
                        }
                    } else {
                        field.setText(currentText + "0.");
                        // 运算符后补0 
                    }
                }
                break;
            default:
                // 数字或运算符按钮
                if (isOperator(text.charAt(0))) {
                    if (!currentText.isEmpty()) {
                        char lastChar = currentText.charAt(currentText.length() - 1);
                        if (isOperator(lastChar)) {
                            // 替换最后一个运算符（避免连续运算符） 
                            field.setText(currentText.substring(0, currentText.length() - 1) + text);
                        } else {
                            field.setText(currentText + text);
                        }
                    }
                } else {
                    field.setText(currentText + text);
                }
                break;
        }
    }

    private void calculate() {
        String expression = field.getText();
        expression = expression.replace("×", "*").replace("÷", "/");
         // 将×和÷替换为JavaScript支持的*和/
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("javascript");
        try {
            Object result = engine.eval(expression);
            field.setText(result.toString());
        } catch (ScriptException e) {
            field.setText("运算错误");
            e.printStackTrace();
        }
    }
    // 实现ActionListener接口的方法，处理按钮点击事件 
    @Override
    public void actionPerformed(ActionEvent a) {
        Object source = a.getSource();
        if (source instanceof JButton) {
            JButton btn = (JButton) source;
            String text = btn.getText();
            setBtnText(text);
             // 调用按钮文本处理方法 
        }
    }

    public static void main(String[] args) {
        // 在事件调度线程(EDT)中创建和操作GUI组件，确保线程安全
        SwingUtilities.invokeLater(Calculator::new);
    }
}    